package org.wmine.algo;

import java.awt.Container;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.util.StringTokenizer;
import java.util.Vector;

import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;

public class DT_1 extends JFrame
{
	String [] attribs1;int [] checkCnt;
	String classLbl;final JCheckBox [] cb111;
	int colknt1,cntRow1;int i;String Goalitem;
	String [][]data2;int [] selected;
	public DT_1(final String[]attribs,final int colknt,final int cntRow,final String [][] data)
	{
		attribs1=attribs;colknt1=colknt;cntRow1=cntRow;	data2=data;
		final Container c=this.getContentPane();
		this.setTitle("Select the Attributes");
		JPanel mainPanel=new JPanel();
		mainPanel.setLayout(new GridLayout(colknt+6,1));
		mainPanel.add(new JLabel("Class Label Attribute:"));
		final JComboBox cb=new JComboBox();
		for(int j = 0;j<colknt;j++)	{cb.addItem(attribs[j]);}
		cb.addItemListener(new ItemListener() {
			public void itemStateChanged(ItemEvent e){classLbl=e.getItem().toString();}});
		mainPanel.add(cb);
		
		mainPanel.add(new JLabel(""));mainPanel.add(new JLabel("Select the Attributes:"));
		cb111=new JCheckBox[colknt];checkCnt=new int[colknt];
		ActionListener listener=new ActionListener(){public void actionPerformed(ActionEvent ae){update();}};
		for(i = 0;i<colknt;i++)
		{
			cb111[i]=new JCheckBox(attribs[i]);
			cb111[i].addActionListener(listener);
			mainPanel.add(cb111[i]);
		}
		mainPanel.add(new JLabel(""));
		JButton but1=new JButton("OK");
		but1.setBounds(10,45,110,20);
		mainPanel.add(but1);
		but1.addActionListener(new ActionListener(){public void actionPerformed(ActionEvent ae)
		{
			dispose();
			selected=new int[cb111.length];
			Goalitem=(String) cb.getSelectedItem();
			for(int s=0;s<cb111.length;s++)		{get(s);}
			callDT();
		}});
		c.add(mainPanel);
		this.setBounds(300,200,300,(30*(colknt+1)));
	}
	void get(int i)
	{
		if(Goalitem.equals(attribs1[i]))
		{//System.out.print(Goalitem);
			selected[i]=2;}
		else if(cb111[i].isSelected())
		{
			//System.out.print("ok");
			selected[i]=1;
		}
		else
			selected[i]=0;
		
		
	}
	void callDT()
	{
		new DT11(attribs1,colknt1,cntRow1,data2,selected,classLbl);
	}
	void update()
	{
		//	checkCnt[i]++;
	}
	public static void main(String [] args)
	{
		
	}
}
class DT11
{
	Vector superSet;
	Vector rules;
	Vector gotBit;
	Vector decision;
	int goalIndex;int rowCnt;
	String [][] data4;double [] gains;
	Vector vName;
	public DT11(final String[]attribs,int colknt,final int cntRow,String [][] data,int[]selected,String classLbl)
	{
		int ind=0;
		rowCnt=cntRow;
		data4=data;
		superSet=new Vector();
		rules=new Vector();
		gotBit=new Vector();
		decision=new Vector();
		vName=new Vector();
		
		for(int i=0;i<selected.length;i++)
		{
			if(selected[i]==1)
				//	think whether to have set of indices or that of labels
				superSet.insertElementAt(i,ind++);	
			else if(selected[i]==2)
				goalIndex=i;
		}
		vName=classify(goalIndex);
		System.out.println(">>>>>>>>>>>>>>>>>>>>>>>>>>>>"+superSet.size()+"Goal"+goalIndex);
		for(int i=0;i<superSet.size();i++)
		{
			System.out.println(superSet.elementAt(i));
		}
		System.out.println("Above commented out!");
		//String t="a=b,c=d,e=f";	buildTree(t,-1);
	//	while(true)
	//	{
			if(rules.size()==0)
				buildTree(null,-1);
			//else
			//{
				int pending;
				while((pending=allzeros())!=-1)
				{
					System.out.println("Iterating!!!"+pending);
					buildTree(rules.elementAt(pending).toString(),pending);
					for(int i=0;i<rules.size();i++)
					{
						System.out.print(rules.elementAt(i).toString());
						System.out.print(" >> ");
						System.out.println(gotBit.elementAt(i).toString());
					}
				}
				System.out.println("FINISHED!!!");
				for(int i=0;i<rules.size();i++)
				{
					System.out.print(rules.elementAt(i).toString());
					System.out.print(" >> ");
					System.out.print(decision.elementAt(i).toString());
				}
		//		break;
		//	}
		//}
	}
	public int allzeros()
	{
		int flag=-1;
		for(int i=0;i<gotBit.size();i++)
		{
			if(Integer.parseInt(gotBit.elementAt(i).toString())==0)
			{
				flag=i;//still to branch!
				break;
			}
		}
		return flag;
	}
	
	public void buildTree(String rule,int rulePtr)
	{
		if(rule==null)//start of building it
		{
			Vector temp=findEntropy(rule);
			if(temp.elementAt(0).equals(0))
			{
				/*//all the tuples in the complete database have same label
				 //System.out.println("**************************"+temp.elementAt(1));*/ 
			}
			else
			{
				//System.out.println("///////////////////////////////////////////////////////");
				int minAttribInd=findGains(rule);
				System.out.println(superSet.elementAt(minAttribInd)+">>>>>>><<<<<<<<<<<<<<");
				//3 vectors willbe empty at this time
				Vector v1=classify(Integer.parseInt(superSet.elementAt(minAttribInd).toString()));
				rulePtr=0;
				for(int i=0;i<v1.size();i++)
				{
					String s=""+minAttribInd+"="+v1.elementAt(i).toString();
					rules.insertElementAt(s,rulePtr);
					gotBit.insertElementAt(0,rulePtr);
					System.out.println(s);
				}
				
			}
		}
		else//means you have already started building it
		{
			System.out.println("before temp");
			Vector temp=findEntropy(rule);
			System.out.println("after temp");
			if(temp.elementAt(0).equals(0))
			{
				System.out.println("zero entropy");
				//all the tuples in the complete database have same label
				gotBit.insertElementAt(1,rulePtr);
				decision.insertElementAt(temp.elementAt(1),rulePtr);
				//System.out.println(temp.elementAt(1)); 
			}
			else
			{
				System.out.println("non zero entropy");
				int minAttribInd=findGains(rule);
				/******************/
				System.out.println(minAttribInd);
				Vector query=new Vector();
				StringTokenizer st=new StringTokenizer(rule);
				int tokenKnt=0;	Vector tokens=new Vector();	int ind=0;
				while(st.hasMoreElements())
				{
					String s=st.nextToken(",");
					StringTokenizer st1=new StringTokenizer(s);
					int i=0;
					while(st1.hasMoreElements())
					{
						String s1=st1.nextToken("=");
						tokens.insertElementAt(s1,tokenKnt++);
						if(i==0)
						{query.insertElementAt(s1,ind++);i=1;}
					}
				}
				//System.out.println("Vector length"+tokens.size()+"query count"+query.size());
				/********************/
				Vector v1=classifyQuery(minAttribInd,tokens);
				String s1=rules.elementAt(rulePtr).toString();
				String s2=s1+","+minAttribInd+"="+v1.elementAt(0).toString();
				rules.removeElementAt(rulePtr);
				rules.insertElementAt(s2,rulePtr);
				int index=rules.size();
				for(int i=1;i<v1.size();i++)
				{
					String s3=s1+","+minAttribInd+"="+v1.elementAt(i).toString();
					rules.insertElementAt(s3,index);
					gotBit.insertElementAt(0,index++);
				}
				
			}
		}
	}
	public Vector classify(int index)
	{	
		//System.out.println("in classssssssssssssify!!!!!!!!"+index);
		int size=0;	int ind;Vector vt=new Vector();
		for(int o=0;o<rowCnt;o++)
		{
			if(vt.size()!=0)
			{
				if((ind=vt.indexOf(data4[o][index]))==-1)	
				{
					vt.insertElementAt(data4[o][index], size);
					size++;
				}
			}
			else
			{
				vt.insertElementAt(data4[o][index], size);
				size++;
			}			
		}
		System.out.println("No.of Classes:"+vt.size());
		//for(int y=0;y<vt.size();y++)
		//System.out.println("Class "+(y+1)+":"+vt.get(y));
		//if(index==goalIndex)
		//System.out.println("????????????????????????????????"+vt.size());
		return vt;
	}
	public int findGains(String rule)
	{
		//superSet and the first part of the rule will have indices only!!
		// goalIndex has the index of the goal attribute
		int p=0;
		//double val=1;
		System.out.println(rule);
		int [][]mat;int[]rowSum;int total=0;
		//int []remainingInd;
		Vector remainingInd=new Vector();
		if(rule==null)//find gains of all those in the superSet
		{
			gains=new double[superSet.size()];
			for(int i=0;i<superSet.size();i++)
			{
				//val=1;
				System.out.println(Integer.parseInt(superSet.elementAt(i).toString()));
				Vector tempV=classify(Integer.parseInt(superSet.elementAt(i).toString()));
				mat=new int[tempV.size()][vName.size()];
				rowSum=new int[tempV.size()];
				for(int r=0;r<tempV.size();r++)
				{
					int rsum=0;
					for(int c=0;c<vName.size();c++)
					{
						int cnt=0;
						for(int rr=0;rr<rowCnt;rr++)
						{
							if(data4[rr][Integer.parseInt(superSet.elementAt(i).toString())].equals(tempV.elementAt(r))&&data4[rr][goalIndex].equals(vName.elementAt(c)))
							{
								cnt++;
								//System.out.println("Count:"+cnt);
							}
						}
						mat[r][c]=cnt;
						//System.out.println(mat[r][c]);
						rsum+=cnt;
					}
					rowSum[r]=rsum;
					total+=rsum;
				}
				double ans=0;
				//System.out.println(vName.size()+"/././././//./.");
				for(int r=0;r<tempV.size();r++)
				{
					double sum=0;
					for(int c=0;c<vName.size();c++)
					{
						//System.out.println("this one!!"+rowSum[r]);
						/**********************comment it out**************************/
						sum+=(((double)mat[r][c]/(double)rowSum[r])*(log2((double)mat[r][c]/(double)rowSum[r]))*(-1));
						
					}	
					//System.out.println("Sum!!"+sum);
					ans+=(((double)rowSum[r]/(double)total)*sum);
				}
				gains[i]=ans;
				System.out.println(gains[i]+"##################################");
			}
			return findMin();
		}
		/*********************************************************/
		else//need to fire the query!
		{
			//System.out.println(Integer.parseInt(superSet.elementAt(i).toString()));
			Vector query=new Vector();
			
			StringTokenizer st=new StringTokenizer(rule);
			int tokenKnt=0;	Vector tokens=new Vector();	int ind=0;
			//query=new Vector();
			while(st.hasMoreElements())
			{
				String s=st.nextToken(",");
				StringTokenizer st1=new StringTokenizer(s);
				int i=0;
				while(st1.hasMoreElements())
				{
					String s1=st1.nextToken("=");
					System.out.println(s1);
					tokens.insertElementAt(s1,tokenKnt++);
					if(i==0)
					{query.insertElementAt(s1,ind++);i=1;}
				}
			}
			System.out.println("query count"+query.size()+query.elementAt(0)+">>"+query.indexOf(0));
			int att=superSet.size()-query.size();
			//System.out.print("Attttttttttttt"+att);
			//System.out.print("Attttttttttttt"+att);
			gains=new double[att];////////*********************************
			//remainingInd=new int[att];////********************
			
			//////////////inintializing remainingInd/////////////////////////
			int jRem=0;
			//for(int i=0;i<superSet.size();i++)
			//System.out.println(i+"] "+superSet.elementAt(i).toString());
			//for(int i=0;i<query.size();i++)
			//System.out.println(i+"] "+query.elementAt(i).toString());
			/****************************************
			  
			for(int i=0;i<superSet.size();i++)
			{
				if(query.indexOf(superSet.elementAt(i))==-1)
				{
					System.out.println("remainingg"+remainingInd.size());
					//remainingInd[jRem++]=
					//System.out.println(Integer.parseInt(superSet.elementAt(i).toString()));
					remainingInd.insertElementAt(superSet.elementAt(i),jRem++);
				}
								
			}
			**************************************************/
			//query contains indices on superset and not actual attribute index in the table
			//superset conatins index to table
			int pointer=0;
				for(int j=0;j<superSet.size();j++)
				{
					int flag=0;
					for(int i=0;i<query.size();i++)
					{
						if(j==(Integer.parseInt(query.elementAt(i).toString())))
						{
							//dont include it into remaining
							flag=1;
						}
					}
					if(flag==0)//remaining
					{
						remainingInd.insertElementAt(superSet.elementAt(j),pointer);
						pointer++;
					}
				}
			for(int i=0;i<remainingInd.size();i++)
			  System.out.println(remainingInd.elementAt(i));
			////////////calcualtion of mean for the remaining ones after firing the query
			for(int i=0;i<gains.length;i++)
			{
				//	val=1;				
				Vector tempV=classifyQuery(Integer.parseInt(remainingInd.elementAt(i).toString()),tokens);//gives diff classes in itself
				mat=new int[tempV.size()][vName.size()];
				rowSum=new int[tempV.size()];
				for(int r=0;r<tempV.size();r++)
				{
					int rsum=0;
					for(int c=0;c<vName.size();c++)
					{
						int cnt=0;
						for(int rr=0;rr<rowCnt;rr++)
						{
							///////////
							int flag=0;
							for(int ii=0;ii<tokens.size();ii+=2)
							{
								if(data4[rr][Integer.parseInt(superSet.elementAt(Integer.parseInt(tokens.elementAt(ii).toString())).toString())].equals(tokens.elementAt(ii+1).toString()))
								{}
								else
									flag=1;
							}
							//////////
							if(flag==0)
							{
								if(data4[rr][Integer.parseInt(remainingInd.elementAt(i).toString())].equals(tempV.elementAt(r))&&data4[rr][goalIndex].equals(vName.elementAt(c)))
								{
									cnt++;
								}
							}	
						}
						mat[r][c]=cnt;
						System.out.println("==============================================>"+cnt);
						rsum+=cnt;
					}
					rowSum[r]=rsum;
					total+=rsum;
				}
				double ans=0;
				for(int r=0;r<tempV.size();r++)
				{
					double sum=0;
					for(int c=0;c<vName.size();c++)
					{
						if(mat[r][c]==0)
						{System.out.println("returning "+tempV.elementAt(r).toString()+" >> "+Integer.parseInt(remainingInd.elementAt(i).toString()));return Integer.parseInt(remainingInd.elementAt(i).toString());}
						sum+=(((double)mat[r][c]/(double)rowSum[r])*(log2((double)mat[r][c]/(double)rowSum[r]))*(-1));
					}		
					//if(sum==0)
					//{
						System.out.println("i goooooooooooooooooooooooooooooot it maaaaaaaaaaaaaaaaaaan");
					//}
					System.out.print(sum);
					ans+=(((double)rowSum[r]/(double)total)*sum);
					System.out.println("=="+ans);
				}
				gains[i]=ans;
				System.out.println("==============================================>>>>>>>>>>>>"+ans);
			}
			return findMin();
			/////////////////////////////////////////
		}
		/*********************************************************/
	}
	public Vector classifyQuery(int attribIndex,Vector strTok)
	{
		//2,0=senior
		int size=0;	int ind;Vector vt=new Vector();
		for(int o=0;o<rowCnt;o++)
		{
			if(vt.size()!=0)
			{
				if((ind=vt.indexOf(data4[o][attribIndex]))==-1)	
				{
					int flag=0;
					for(int i=0;i<strTok.size();i+=2)
					{
						if(data4[o][Integer.parseInt(superSet.elementAt(Integer.parseInt(strTok.elementAt(i).toString())).toString())].equals(strTok.elementAt(i+1).toString()))
						{}
						else
							flag=1;
					}
					if(flag==0)
					{
						vt.insertElementAt(data4[o][attribIndex], size);
						size++;
					}
				}
			}
			else
			{
				int flag=0;
				for(int i=0;i<strTok.size();i+=2)
				{
					if(data4[o][Integer.parseInt(superSet.elementAt(Integer.parseInt(strTok.elementAt(i).toString())).toString())].equals(strTok.elementAt(i+1).toString()))
					{}
					else
						flag=1;
				}
				if(flag==0)
				{
					vt.insertElementAt(data4[o][attribIndex], size);
					size++;
				}
			}			
		}
		System.out.println("No.of Classes:"+vt.size());
		for(int y=0;y<vt.size();y++)
		System.out.println("Class "+(y+1)+":"+vt.get(y));
		return vt;
	}
	public int findMin()
	{
		int minPtr=-1;
		if(gains.length!=0)
		{
			double min=gains[0];
			minPtr=0;
			for(int i=0;i<gains.length;i++)
			{
				if(min>gains[i])
				{
					min=gains[i];
					minPtr=i;
				}
			}
		}
		return minPtr;
	}
	public static double log2(double d) {
		return Math.log(d)/Math.log(2.0);
	}
	public Vector findEntropy(String rule)
	{
		Vector temp=new Vector();
		if(rule==null)
		{
			String match=data4[0][goalIndex];
			for(int i=0;i<rowCnt;i++)
			{
				if(data4[i][goalIndex].equals(match))
					;				
				else
				{
					temp.insertElementAt(1,0);
					return temp;
				}
			}
			temp.insertElementAt(0,0);
			temp.insertElementAt(match,1);
			return temp;
		}
		else
		{
			StringTokenizer st=new StringTokenizer(rule);
			int tokenKnt=0;
			Vector tokens=new Vector();
			while(st.hasMoreElements())
			{
				String s=st.nextToken(",");
				StringTokenizer st1=new StringTokenizer(s);
				while(st1.hasMoreElements())
				{
					String s1=st1.nextToken("=");
					tokens.insertElementAt(s1,tokenKnt++);						
				}
			}
			System.out.println("iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiVector length"+tokens.size());
			///////////////////////
			String match=data4[0][goalIndex];
			for(int i=0;i<rowCnt;i++)
			{
				if(data4[i][goalIndex].equals(match))
				{
					for(int k=0;k<tokens.size();k+=2)
					{
						if(data4[i][Integer.parseInt(superSet.elementAt(Integer.parseInt(tokens.elementAt(k).toString())).toString())].equals(tokens.elementAt(k+1)))
							;
						else
						{
							temp.insertElementAt(1,0);
							return temp;
						}						
					}
					temp.insertElementAt(0,0);
					temp.insertElementAt(match,1);
					return temp;
				}			
				else
				{
					temp.insertElementAt(1,0);
					return temp;
				}
			}
			temp.insertElementAt(0,0);
			temp.insertElementAt(match,1);
			return temp;
			
			
			//////////////////////////			
		}
	}
	
}